#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <sys/time.h>
using namespace std;
static const uint16_t port = 8080;
struct conn_t
{
    conn_t()
        : net_fd(-1), alive(0), last_time(0)
    {
    }
    conn_t(const int fd, const int al, time_t t)
        : net_fd(fd), alive(al), last_time(t)
    {
    }
    int net_fd;
    int alive;
    time_t last_time;
};
int main(int argc, char *argv[])
{
    int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    int reuse = 1;
    setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_addr.s_addr = htonl(INADDR_ANY);
    local.sin_port = htons(port);
    bind(socket_fd, (struct sockaddr *)&local, sizeof(local));
    listen(socket_fd, 10);
    vector<conn_t> list;
    list.resize(100);
    fd_set base_set;
    FD_ZERO(&base_set);
    FD_SET(socket_fd, &base_set);
    while (true)
    {
        fd_set set;
        FD_ZERO(&set);
        memcpy(&set, &base_set, sizeof(base_set));
        struct timeval tv;
        tv.tv_sec = 1;
        tv.tv_usec = 0;
        select(10, &set, nullptr, nullptr, &tv);
        if (FD_ISSET(socket_fd, &set))
        {
            int net_fd = accept(socket_fd, nullptr, nullptr);
            list.push_back(conn_t(net_fd, 0, time(nullptr)));
            FD_SET(net_fd, &base_set);
        }
        for (int i = 0; i < list.size(); i++)
        {
            if (list[i].alive == 0 && FD_ISSET(list[i].net_fd, &set))
            {
                char buffer[1024] = {0};
                int ret_recv = recv(list[i].net_fd, &buffer, sizeof(buffer), 0);
                if (ret_recv == 0)
                {
                    list[i].alive = 1;
                    FD_CLR(list[i].net_fd, &base_set);
                    close(list[i].net_fd);
                    continue;
                }
                else
                {
                    for (int j = 0; j < list.size(); j++)
                    {
                        if (list[j].alive == 0 && list[i].net_fd != list[j].net_fd)
                        {
                            send(list[j].net_fd, buffer, ret_recv, 0);
                        }
                    }
                    time(&list[i].last_time);
                }
            }
        }
        for (int k = 0; k < list.size(); k++)
        {
            time_t now_time;
            time(&now_time);
            if (list[k].alive == 0 && (now_time - list[k].last_time) >= 30)
            {
                FD_CLR(list[k].net_fd, &base_set);
                list[k].alive = 1;
                close(list[k].net_fd);
            }
        }
    }
    close(socket_fd);
    return 0;
}